package lumis.service.mailmarketing;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import org.hibernate.Criteria;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import lumis.content.ContentStringResource;
import lumis.portal.PortalException;
import lumis.portal.UnexpectedException;
import lumis.portal.authentication.SessionConfig;
import lumis.portal.clock.ClockConfig;
import lumis.portal.dao.hibernate.ITransactionHibernate;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.sendmail.IMailBody;
import lumis.portal.sendmail.IMailDestination;
import lumis.portal.sendmail.IMultipleMail;
import lumis.portal.service.GenericServiceClock;
import lumis.portal.service.ServiceException;
import lumis.portal.transaction.PortalTransactionFactory;
import lumis.portal.user.UserConfig;
import lumis.util.IResource;
import lumis.util.ITransaction;

/**
 * Searches for bulletins that are waiting to be published and publishes them.
 * 
 * @version $Revision: 8948 $ $Date: 2008-02-29 12:40:36 -0300 (Fri, 29 Feb 2008) $
 * @since 4.0.6
 */
public class MailMarketingClock extends GenericServiceClock
{

	@SuppressWarnings("unchecked")
	public void doTick(SessionConfig sessionConfig, ClockConfig clockConfig) throws ServiceException, PortalException
	{
		ITransaction transaction = PortalTransactionFactory.createTransaction();
		try
		{
			transaction.begin();

			IResource resource = new ContentStringResource();
			resource.addResourcePath("lumis/service/mailmarketing/strings/strings");

			ITransactionHibernate transactionHib = (ITransactionHibernate) transaction;
			Session session = transactionHib.getSession();

			Criteria criteria = session.createCriteria(Bulletin.class);

			criteria.add(Restrictions.eq("status", Bulletin.STATUS_READY_FOR_PUBLISHING));
			criteria.add(Restrictions.le("sendDateTime", new Date()));

			Collection<Bulletin> bulletins = criteria.list();
			for (Bulletin bulletin : bulletins)
			{
				// get category ids for this bulletin
				Collection<Category> categories = bulletin.getCategories();
				if (categories.isEmpty())
					continue;
				Collection<String> categoryIds = new ArrayList<String>(categories.size());
				for (Category category: categories)
					categoryIds.add(category.getId());

				// send email for this bulletin
				IMultipleMail mail = ManagerFactory.getSendMailManager().createMultipleMail();
				mail.setSourceComponent("STR_MAIL_MARKETING_CLOCK");
				mail.setSourceComponentStringsUrl("lumis/service/mailmarketing/strings/strings");
				mail.setFrom(bulletin.getSenderEmail());
				mail.setSubject(bulletin.getSubject());
				IMailBody emailBody = mail.getBody();
				emailBody.setHtmlMsg(bulletin.getContent());
				bulletin.setStatus(Bulletin.STATUS_SENT);
				
				// now get the users that subscribed to these categories
				ScrollableResults scrollableResults = session.createCriteria(UserSubscription.class)
						.createAlias("categories", "cat")
						.add(Restrictions.in("cat.id", categoryIds))
						.scroll();
				try
				{
					while (scrollableResults.next())
					{
						UserSubscription userSubscription = (UserSubscription) scrollableResults.get(0);

						UserConfig userConfig = null;
						
						if(userSubscription.getUserId() != null)
							userConfig = ManagerFactory.getUserManager().get(sessionConfig, userSubscription.getUserId(), transaction);
						
						String email = userSubscription.getEmail();
						
						if(email == null && userConfig != null)
							email = userConfig.getEmail();

						if (email != null)
						{
							IMailDestination destination = ManagerFactory.getSendMailManager().createMailDestination();
							destination.setEmailAddress(email);
							
							if(userConfig != null)
								destination.setName(userConfig.getFullName());
							
							mail.getDestinations().add(destination);
						}

						session.evict(userSubscription);
					}
				}
				finally
				{
					scrollableResults.close();
				}

				// if there is no destination, there is no mail to send
				if (mail.getDestinations().isEmpty())
					continue;

				ManagerFactory.getSendMailManager().addMailToSendQueue(sessionConfig, mail, null, transaction);
			}

			transaction.commit();
		}
		catch (PortalException e)
		{
			transaction.rollback();
			throw e;
		}
		catch (Exception e)
		{
			transaction.rollback();
			throw new UnexpectedException(e);
		}
		finally
		{
			transaction.dispose();
		}

	}

}
